import { createServer } from 'http'
import { Server, Socket } from 'socket.io'
import { WSMessageType } from '../types/ws'
import { verifyToken } from '../utils/backend/auth'
import { prisma } from '../utils/backend/db'

interface CustomSocket extends Socket {
	userId?: number
}

type OnlineStatus = 'online' | 'offline'

const httpServer = createServer()
const io = new Server(httpServer, {
	cors: {
		origin: process.env.NEXT_PUBLIC_BASE_URL,
		methods: ['GET', 'POST'],
		credentials: true,
	},
})

// 存储连接的客户端
const clients = new Map()

const handleUserOnlineStatus = async (socket: CustomSocket, status: OnlineStatus) => {
	// 更新数据库用户状态
	await prisma.user.update({
		where: { id: socket.userId },
		data: { status: status },
	})

	// 获取用户的所有好友
	const friends = await prisma.friend.findMany({
		where: {
			OR: [
				{ senderId: socket.userId, status: 'accepted' },
				{ receiverId: socket.userId, status: 'accepted' },
			],
		},
		include: {
			sender: true,
			receiver: true,
		},
	})

	// 向所有在线的好友广播状态
	// 获取所有好友的ID
	const friendIds = friends.map((f) => (f.senderId === socket.userId ? f.receiverId : f.senderId))
	console.log('friendIds', friendIds)
	// 向每个在线的好友推送状态
	friendIds.forEach((friendId) => {
		const friendSocket = clients.get(friendId)
		if (!friendSocket) return // 好友不在线，则不必推送
		friendSocket.emit(WSMessageType.STATUS, {
			friendId: socket.userId,
			status: status,
		})
	})
}

const handleMessage = async (data: any, socket: CustomSocket) => {
	try {
		const { chatId, content } = data
		if (!socket.userId) return

		// 获取聊天信息
		const chat = await prisma.privateChat.findUnique({
			where: { id: chatId },
		})

		if (!chat) return

		// 确定接收者ID
		const receiverId = chat.user1Id === Number(socket.userId) ? chat.user2Id : chat.user1Id

		// 创建消息
		const message = await prisma.privateMessage.create({
			data: {
				content,
				chatId,
				senderId: Number(socket.userId),
				type: 'text',
				status: 'sent',
			},
			include: {
				sender: {
					select: { id: true, username: true, nickname: true, avatar: true },
				},
			},
		})
		// 推送给发送者
		socket.emit(WSMessageType.MESSAGE, message)
		// 推送给接收者
		const receiverSocket = clients.get(receiverId)
		if (receiverSocket) {
			receiverSocket.emit(WSMessageType.MESSAGE, message)
		}

		// 确认消息发送
		socket.emit('messageConfirm', {
			messageId: message.id,
			status: 'sent',
		})

		// 调试输出
		console.log('Sending message to socket:', socket.id, message)
	} catch (error) {
		console.error('Send message error:', error)
	}
}

io.use(async (socket: CustomSocket, next) => {
	const token = socket.handshake.auth.token?.replace('Bearer ', '')
	const userId = socket.handshake.auth.userId
	const tokenResult = await verifyToken(token)

	if (!token || !userId || !tokenResult.valid) {
		return next(new Error('Authentication error'))
	}

	socket.userId = userId
	next()
})

io.on('connection', async (socket: CustomSocket) => {
	const userId = socket.userId

	// 存储连接
	clients.set(userId, socket)
	console.log('用户连接了ws')

	// 更新用户状态为在线
	handleUserOnlineStatus(socket, 'online')

	// 监听前端发送的消息，并通过ws推送给当前聊天室的自己和好友
	socket.on(WSMessageType.MESSAGE, (data: any) => handleMessage(data, socket))

	// 监听前端发送私聊
	socket.on(WSMessageType.PRIVATE_CHAT, (data: any) => handlePrivateChat(data, socket))

	// 断开连接
	socket.on('disconnect', async () => {
		console.log('用户断开了ws')
		handleUserOnlineStatus(socket, 'offline')
		clients.delete(userId)
	})
})

const handlePrivateChat = async (data: any, socket: CustomSocket) => {
	try {
		const { friendId } = data
		const currentUserId = socket.userId!

		// 查找或创建私聊聊天室
		const chat = await prisma.privateChat.upsert({
			where: {
				user1Id_user2Id: {
					user1Id: Math.min(currentUserId, friendId),
					user2Id: Math.max(currentUserId, friendId),
				},
			},
			create: {
				user1Id: Math.min(currentUserId, friendId),
				user2Id: Math.max(currentUserId, friendId),
			},
			update: {},
			include: {
				user1: true,
				user2: true,
				messages: {
					take: 1,
					orderBy: {
						createdAt: 'desc',
					},
				},
			},
		})

		// 构造返回的聊天数据
		const formattedChat = {
			id: chat.id,
			unreadCount: 0, // 新建的聊天，未读消息为0
			updatedAt: chat.updatedAt.toISOString(),
			// 如果当前用户是user1，则contact是user2，反之亦然
			contact: chat.user1Id === currentUserId ? chat.user2 : chat.user1,
			lastMessage: chat.messages[0]?.content || null,
		}

		// 推送给发送者当前激活的聊天室
		socket.emit(WSMessageType.PRIVATE_CHAT, {
			activeChat: formattedChat,
		})
	} catch (error) {
		console.error('ws send private chat failed:', error)
	}
}

httpServer.listen(8080, () => {
	console.log('WebSocket server running on port 8080')
})
